package org.yray.sip.handler;


import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.yray.sip.base.MsgType;
import org.yray.sip.base.OkType;
import org.yray.sip.base.SipMsg;
import org.yray.sip.creator.MessageCreator;
import org.yray.sip.handler.err.*;
import org.yray.sip.handler.flow.*;
import org.yray.sip.log.AbstractLog;
import org.yray.sip.rtp.receive.AbstractBeanHolder;
import org.yray.sip.rtp.receive.IComm;
import org.yray.sip.rtp.sender.ISipSessionCache;
import org.yray.sip.rtp.sender.SipSessionCache;
import org.yray.sip.server.SipServerContext;
import org.yray.sip.server.SipSession;
import org.yray.sip.utils.IcspBeanHolder;
import org.yray.sip.visit.ISipAccept;
import org.yray.sip.visit.SipVisitorFactory;

import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
public abstract class MessageHandler extends AbstractBeanHolder implements IComm {

     public static final  String[] BLANK_STRINGS=new String[]{};

     
     private static Map<MsgType,MessageHandler> handlerMap=new EnumMap(MsgType.class);

     protected static Map<OkType,MessageHandler> okHandlerMap=new EnumMap(OkType.class);

     public static void addHandler(MsgType msgType, MessageHandler handler)
     {
          handlerMap.put(msgType,handler);
     }

     public static void addOkHandler(OkType msgType, MessageHandler handler)
     {
          okHandlerMap.put(msgType,handler);
     }

     public abstract String[] handler(SipMsg sipMsg, SipServerContext ssc);


     public static String[] doMess(SipMsg sipMsg,  SipServerContext ssc)
     {
          log(sipMsg);
          MessageHandler messageHandler=handlerMap.get(sipMsg.getMsgType());
          if(messageHandler==null)
          {
               try {
                    AbstractLog.log(sipMsg.getCallId(), "MessageHandler", "messageHandler is null");
               }catch (Exception e)
               {
                    log.error("sip message err={}", sipMsg);
               }
               return BLANK_STRINGS;
          }
          AbstractLog.log(sipMsg.getCallId(),messageHandler.getClass().getName(),"messageHandler");
          return messageHandler.handler(sipMsg,ssc);
     }



     public static void log(SipMsg sipMsg)
     {
          SipSession sipSession=IcspBeanHolder.getBean(ISipSessionCache.class).get(sipMsg.getCallId());
          if(sipSession!=null)
          {
               if(sipSession.getSourceId()!=null)
               {
                    SipSession aSipSession=IcspBeanHolder.getBean(ISipSessionCache.class).get(sipMsg.getCallId());
                    if(aSipSession!=null)
                    {
                         aSipSession.addSipMsg(sipMsg.toString());
                    }
                    else {
                         log.info("sipMsg={}", sipMsg);
                    }
               }
               else {
                    sipSession.addSipMsg(sipMsg.toString());
               }

          }else {
               log.info("sipMsg={}", sipMsg);
          }
     }

     static {
          //消息处理工场
          MessageHandler.addHandler(MsgType.UNAUTHORIZED,new UnauthorizedHandler());
          MessageHandler.addHandler(MsgType.INVITE,new InviteHandler());
          MessageHandler.addHandler(MsgType.OK,new OK200Handler());
          MessageHandler.addHandler(MsgType.NOTIFY,new NotifyHandler());
          MessageHandler.addHandler(MsgType.PROGRESS183,new Progress183Handler());
          MessageHandler.addHandler(MsgType.RINGING180,new Ringing180Handler());
          MessageHandler.addHandler(MsgType.TRYING,new Trying100Handler());
          MessageHandler.addHandler(MsgType.BYE,new ByeHandler());
          MessageHandler.addHandler(MsgType.NOT_FOUND_404,new NotFound404Handler());
          MessageHandler.addHandler(MsgType.REQUEST_TIMEOUT_408,new RT408Handler());
          MessageHandler.addHandler(MsgType.BUSY_486,new Busy486Handler());
          MessageHandler.addHandler(MsgType.REQUEST_TERMINATED_487,new RT487Handler());
          MessageHandler.addHandler(MsgType.NOT_ACCEPTABLE_488,new NAH488Handler());
          MessageHandler.addHandler(MsgType.UNAVAILABLE_480,new TU480Handler());
          MessageHandler.addHandler(MsgType.INTERNAL_SERVER_ERROR_500,new ISE500Handler());
          MessageHandler.addHandler(MsgType.SERVICE_UNAVAILABLE_503,new SU503Handler());
          MessageHandler.addHandler(MsgType.DECLINE_603,new Decline603Handler());
          MessageHandler.addHandler(MsgType.E5XX,new E5XXHandler());
          MessageHandler.addHandler(MsgType.E4XX,new E4XXHandler());
          MessageHandler.addHandler(MsgType.TRANSACTION_NOT_481,new TransactionNotHandler());
          MessageHandler.addHandler(MsgType.CANCEL,new CancelHandler());
          MessageHandler.addHandler(MsgType.REGISTER,new RegisterHandler());
          MessageHandler.addOkHandler(OkType.OK_CANCEL, OK_CancelHandler.instance);
          MessageHandler.addOkHandler(OkType.OK_INVITE, OK_InviteHandler.instance);
          MessageHandler.addOkHandler(OkType.OK_DEFAULT, OK_DefaultHandler.instance);
          MessageHandler.addOkHandler(OkType.OK_REGISTER, OK_RegisterHandler.instance);
          MessageHandler.addOkHandler(OkType.OK_NOTIFY,OK_DefaultHandler.instance);
          MessageHandler.addOkHandler(OkType.OK_BYE, OK_ByeHandler.instance);
     }


     public String handlerErr(SipMsg sipMsg, SipServerContext ssc)
     {
          String callId= sipMsg.getCallId();
          ISipAccept sipAccept=getSipVisitorFactory().getSipAccept(callId);
          sipAccept.accept(SipVisitorFactory.SIP_ERR_VISITOR,sipMsg,ssc);
          SipSession sipSession= IcspBeanHolder.getBean(ISipSessionCache.class).get(callId);
          sipSession= Optional.ofNullable(sipSession).orElse(
                  new SipSession(sipMsg, ssc.getRunIp(), ssc.getRunPort(), false));
          //主要的处理异常情况的sip报文回复
          String result = MessageCreator.getCreator(MsgType.ACK).createMsg(sipSession);
          return result;
     }
}
